using Microsoft.Extensions.Logging;
using KnowledgeQA.Core.Interfaces;
using KnowledgeQA.Models.Entities;
using System.Text.Json;

namespace KnowledgeQA.Core.Implementations
{
    /// <summary>
    /// 内存向量服务实现类（带持久化）
    /// </summary>
    public class InMemoryVectorService : IVectorService
    {
        private readonly ILogger<InMemoryVectorService> _logger;
        private readonly Dictionary<string, VectorData> _vectors = new();
        private readonly object _lock = new();
        private readonly string _dataFilePath;

        public InMemoryVectorService(ILogger<InMemoryVectorService> logger)
        {
            _logger = logger;
            _dataFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "vector_data.json");
            LoadVectorsFromFile();
        }

        public string VectorDbType => "InMemory";

        public async Task<bool> AddVectorAsync(string vectorId, float[] vector, Dictionary<string, object>? metadata = null)
        {
            try
            {
                lock (_lock)
                {
                    _vectors[vectorId] = new VectorData
                    {
                        VectorId = vectorId,
                        Vector = vector,
                        Metadata = metadata ?? new Dictionary<string, object>()
                    };
                }

                await SaveVectorsToFile();
                _logger.LogInformation("向量已添加: {VectorId}", vectorId);
                return true;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "添加向量失败: {VectorId}", vectorId);
                return false;
            }
        }

        public async Task<bool> AddVectorsAsync(IEnumerable<VectorData> vectors)
        {
            try
            {
                lock (_lock)
                {
                    foreach (var vector in vectors)
                    {
                        _vectors[vector.VectorId] = vector;
                    }
                }
                _logger.LogInformation("批量添加向量，数量: {Count}", vectors.Count());
                await SaveVectorsToFile();
                _logger.LogInformation("批量添加向量成功，数量: {Count}", vectors.Count());
                return true;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "批量添加向量失败");
                return false;
            }
        }

        public async Task<bool> DeleteVectorAsync(string vectorId)
        {
            try
            {
                lock (_lock)
                {
                    if (_vectors.ContainsKey(vectorId))
                    {
                        _vectors.Remove(vectorId);
                        _logger.LogInformation("向量已删除: {VectorId}", vectorId);
                        SaveVectorsToFile().Wait();
                        return true;
                    }
                }

                return false;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "删除向量失败: {VectorId}", vectorId);
                return false;
            }
        }

        public async Task<bool> DeleteVectorsAsync(IEnumerable<string> vectorIds)
        {
            try
            {
                lock (_lock)
                {
                    var deletedCount = 0;
                    foreach (var vectorId in vectorIds)
                    {
                        if (_vectors.ContainsKey(vectorId))
                        {
                            _vectors.Remove(vectorId);
                            deletedCount++;
                        }
                    }

                    _logger.LogInformation("批量删除向量成功，数量: {Count}", deletedCount);
                    SaveVectorsToFile().Wait();
                    return deletedCount > 0;
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "批量删除向量失败");
                return false;
            }
        }

        public async Task<List<VectorSearchResult>> SearchAsync(float[] queryVector, int topK = 5, double minScore = 0.7, Dictionary<string, object>? filter = null)
        {
            try
            {
                var results = new List<VectorSearchResult>();

                lock (_lock)
                {
                    foreach (var kvp in _vectors)
                    {
                        var vector = kvp.Value;
                        
                        // 应用过滤条件
                        if (filter != null && !MatchesFilter(vector.Metadata, filter))
                        {
                            continue;
                        }

                        var score = CalculateCosineSimilarity(queryVector, vector.Vector);
                        
                        if (score >= minScore)
                        {
                            results.Add(new VectorSearchResult
                            {
                                VectorId = vector.VectorId,
                                Score = score,
                                Metadata = vector.Metadata
                            });
                        }
                    }
                }

                // 按相似度排序并返回topK结果
                var sortedResults = results.OrderByDescending(r => r.Score).Take(topK).ToList();
                
                _logger.LogInformation("向量搜索完成，查询结果数量: {Count}", sortedResults.Count);
                return sortedResults;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "向量搜索失败");
                return new List<VectorSearchResult>();
            }
        }

        public async Task<bool> UpdateVectorAsync(string vectorId, float[] vector, Dictionary<string, object>? metadata = null)
        {
            try
            {
                lock (_lock)
                {
                    if (_vectors.ContainsKey(vectorId))
                    {
                        _vectors[vectorId] = new VectorData
                        {
                            VectorId = vectorId,
                            Vector = vector,
                            Metadata = metadata ?? _vectors[vectorId].Metadata
                        };

                        _logger.LogInformation("向量已更新: {VectorId}", vectorId);
                        SaveVectorsToFile().Wait();
                        return true;
                    }
                }

                return false;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "更新向量失败: {VectorId}", vectorId);
                return false;
            }
        }

        public async Task<VectorData?> GetVectorAsync(string vectorId)
        {
            try
            {
                lock (_lock)
                {
                    if (_vectors.TryGetValue(vectorId, out var vector))
                    {
                        return vector;
                    }
                }

                return null;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取向量失败: {VectorId}", vectorId);
                return null;
            }
        }

        public async Task<bool> IsAvailableAsync()
        {
            try
            {
                // 内存向量服务总是可用的
                return true;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "检查向量服务可用性失败");
                return false;
            }
        }

        public async Task<VectorDbStats> GetStatsAsync()
        {
            try
            {
                lock (_lock)
                {
                    var stats = new VectorDbStats
                    {
                        TotalVectors = _vectors.Count,
                        VectorDimension = _vectors.Values.FirstOrDefault()?.Vector.Length ?? 0,
                        IndexSize = _vectors.Count * sizeof(float) * (_vectors.Values.FirstOrDefault()?.Vector.Length ?? 0),
                        LastUpdated = DateTime.Now
                    };

                    return stats;
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取向量数据库统计信息失败");
                return new VectorDbStats();
            }
        }

        /// <summary>
        /// 从文件加载向量数据
        /// </summary>
        private void LoadVectorsFromFile()
        {
            try
            {
                if (File.Exists(_dataFilePath))
                {
                    var json = File.ReadAllText(_dataFilePath);
                    var vectors = JsonSerializer.Deserialize<Dictionary<string, VectorData>>(json);
                    
                    lock (_lock)
                    {
                        _vectors.Clear();
                        if (vectors != null)
                        {
                            foreach (var kvp in vectors)
                            {
                                _vectors[kvp.Key] = kvp.Value;
                            }
                        }
                    }
                    
                    _logger.LogInformation("从文件加载向量数据成功，数量: {Count}", _vectors.Count);
                }
                else
                {
                    _logger.LogInformation("向量数据文件不存在，将创建新的向量数据库");
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "从文件加载向量数据失败");
            }
        }

        /// <summary>
        /// 保存向量数据到文件
        /// </summary>
        private async Task SaveVectorsToFile()
        {
            try
            {
                Dictionary<string, VectorData> vectorsCopy;
                lock (_lock)
                {
                    vectorsCopy = new Dictionary<string, VectorData>(_vectors);
                }

                var json = JsonSerializer.Serialize(vectorsCopy, new JsonSerializerOptions 
                { 
                    WriteIndented = true,
                    MaxDepth = 64
                });
                
                await File.WriteAllTextAsync(_dataFilePath, json);
                _logger.LogDebug("向量数据已保存到文件，数量: {Count}", vectorsCopy.Count);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "保存向量数据到文件失败");
            }
        }

        private double CalculateCosineSimilarity(float[] vector1, float[] vector2)
        {
            if (vector1.Length != vector2.Length)
            {
                return 0;
            }

            var dotProduct = 0.0f;
            var norm1 = 0.0f;
            var norm2 = 0.0f;

            for (int i = 0; i < vector1.Length; i++)
            {
                dotProduct += vector1[i] * vector2[i];
                norm1 += vector1[i] * vector1[i];
                norm2 += vector2[i] * vector2[i];
            }

            norm1 = (float)Math.Sqrt(norm1);
            norm2 = (float)Math.Sqrt(norm2);

            if (norm1 == 0 || norm2 == 0)
            {
                return 0;
            }

            return dotProduct / (norm1 * norm2);
        }

        private bool MatchesFilter(Dictionary<string, object> metadata, Dictionary<string, object> filter)
        {
            foreach (var kvp in filter)
            {
                if (!metadata.ContainsKey(kvp.Key) || !metadata[kvp.Key].Equals(kvp.Value))
                {
                    return false;
                }
            }
            return true;
        }
    }
} 